/*
 Xern Entity Relocation Network
 Copyright (C) 2010-2011 Ronie Salgado <roniesalg@gmail.com>

 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.

 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 Lesser General Public License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with this library; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
*/

#include <OgreEntity.h>
#include "Xern/Entity.hpp"
#include "Xern/Engine.hpp"
#include "Xern/Exceptions.hpp"
#include "Xern/ResourceManager.hpp"
#include "Geometry.hpp"
#include "GeometryInstance.hpp"
#include "Material.hpp"

#include "OgreRenderer.hpp"

namespace XernOgre
{
	Geometry::Geometry(boost::shared_ptr<OgreRenderer> renderer,
			Ogre::SceneManager *scene, Ogre::MeshPtr mesh)
		: renderer(renderer), scene(scene), mesh(mesh)
	{
		castShadow = true;
		id = nil_uuid();
	}

	Geometry::~Geometry()
	{
	}

	Ogre::MeshPtr Geometry::GetMesh() const
	{
		return mesh;
	}

	IResource::ResourceFlags Geometry::GetFlags() const
	{
		return ResourceFlags(RFL_MOVABLE_OBJECT | RFL_CASHEABLE);
	}

	void Geometry::UpdateState(boost::shared_ptr<IDataFilter> stateData)
	{
	}

	const uuid &Geometry::GetId() const
	{
		return this->id;
	}

	void Geometry::SetId(const uuid &id)
	{
		this->id = id;
	}

	void Geometry::SetMaterial(const std::string &name)
	{
		this->materialName = name;
	}

	void Geometry::SetMaterial(boost::shared_ptr<IMaterial> material)
	{
		if(!material)
			return;

		boost::shared_ptr<Material> omat = boost::dynamic_pointer_cast<Material> (material);
		materialName = omat->material->getName();
		this->material = material;
	}

	boost::shared_ptr<IMaterial> Geometry::GetMaterial() const
	{
		return this->material;
	}

	const std::string &Geometry::GetMaterialName() const
	{
		return materialName;
	}

	AABox Geometry::GetBoundingBox() const
	{
		const Ogre::AxisAlignedBox &box = mesh->getBounds();
		const Ogre::Vector3 &min = box.getMinimum();
		const Ogre::Vector3 &max = box.getMaximum();
		return AABox(Vector3(min.x, min.y, min.z),
					 Vector3(max.x, max.y, max.z));	}

	void Geometry::SetBoundingBox(const AABox &box)
	{
	}

	boost::shared_ptr<IGeometryInstance> Geometry::CreateInstance() const
	{
		boost::shared_ptr<IGeometryInstance> ret(new GeometryInstance(shared_from_this(), renderer, scene));
		Engine::Get().GetResourceManager()->RegisterExternalResource(ret);
		return ret;
	}

	void Geometry::UploadVertices(int buffer, size_t len, const void *data)
	{
		Ogre::VertexBufferBinding* bind = mesh->sharedVertexData->vertexBufferBinding;
		Ogre::HardwareVertexBufferSharedPtr bufferPtr = bind->getBuffer(buffer);
		bufferPtr->writeData(0, len, data, true);
	}

	void Geometry::SetShadowCasting(bool shadow)
	{
		castShadow = shadow;
	}

	bool Geometry::GetShadowCasting() const
	{
		return castShadow;
	}

};
